/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
	/******************************************************************************
          线性CCD摄像头智能车新教学程序
          
          版权号 (C), 2022-2023,  设计人：王璠
          
          版本:V0.2   2022-11-20	
					版本:V0.3   2022-12-8 完成舵机，电机驱动，OLED显示驱动，按键，拨盘开关驱动
																串口1驱动，摄像头数据采集驱动程序编写
					版本:V0.4   2022-12-？？											

 ******************************************************************************
    线性CCD(TsL1401)说明: 
          线性CCD接线：从左到右
        1  GND   电源地
        2  VCC 电源正：5V/3.3V
        3  CLK  PC0 宏为 CCD_LIN_CK 时钟输入，控制电荷转移，像素点输出和复位
        4  SI  PC1 宏为 CCD_LIN_SI 序列输入，标志数据序列的数据
        5  AO  PA0 CCD模拟信号输出到STM32F407VEC6的ADC1转换器
******************************************************************************/ 
	
	
	
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
#include "chinese.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "stm32f4xx.h"
#include "stm32f4xx_it.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */




/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
 /*----------------------------------------------------------------------------*
 * 宏定义                                                                      *
 *-----------------------------------------------------------------------------*/
#define  KEY HAL_GPIO_ReadPin(GPIOC, key_Pin)

/* USER CODE END PD */


/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
void SYSTEM_ATD_Init(void);                     //  A/D转换器初始化


void CCD_LIN_GetImage(unsigned char *pucImageBuf,unsigned char exposure_time);
//输入参数  : UCHAR8 *pucImageBuf  存放128个AD转换结果的缓存地址指针，
//							exposure_time：曝光时间
// 输出参数  : pucImageBuf  128个AD转换结果 8位）
void CCD_LIN_GetImage_new(unsigned char *pucImageBuf);
void CCD_LIN_Init(void);//线性CCD初始化

void CCD_LIN_Delay(unsigned int CCD_DELAY_TIME);

void CCD_DATA_P(void);
void CCD_DATA_Process(void);
void Dly_ms(int ms);          //延时子程序

void  rudeer1_control(unsigned int pwm_value_rudder);	//舵机ch1转向角度控制
void  rudeer2_control(unsigned int pwm_value_rudder);	//舵机ch2转向角度控制
void  moto1_speed_control(unsigned char pwm_value_motor);//电机1速度设置
void  moto2_speed_control(unsigned char pwm_value_motor);//电机2速度设置


/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */



/********************************************************/

	uint8_t keydown_flag =0;
	uint8_t int_flag =0;
	
/********************************************************/
//         智能车舵机中心（正）值设置
	uint16_t pwm_value_rudder_middle =1730;	//舵机转向角度初始中心(6号车)
//	uint16_t pwm_value_rudder_middle =1900;	//舵机转向角度初始中心(1号车)
//	uint16_t pwm_value_rudder_middle =1740;	//舵机转向角度初始中心(2号车)
/********************************************************/
//         智能车舵机转向角度，范围1460-1660(中心)-1860
uint16_t pwm_value_rudder = 1300;	//舵机转向角度初始默认1460-1660(中心)-1860
uint16_t pwm_value_rudder2 = 1300;	//舵机转向角度ch2
/*******************************************************/	
//         智能车电机速度，范围8-60
uint16_t pwm_value_motor_def = 38;	//电机速度初始默认值设罿
uint16_t pwm_value_motor = 38;	//电机速度
/*******************************************************/	

	uint16_t pwm_value_rudder_test;
	char adc_8bit;
	uint16_t adc_value =0;
	float voltage =0.0;
	char voltString[120] ={0};

 
 
unsigned char aucImageBuf[128]; //存放线性CCD数据的存储器

unsigned char exposure_time=100;//	CCD曝光时间(20us*exposure_time), 200为缺省值

unsigned char CCDBuf[128]; //存放线性CCD数据的存储器备份
	
int CCD_black=63,Last_CCD_black=63;
	
unsigned int  CCD_DELAY_TIME=200;  //线性CCD延时时间设置   原默认为150
	
unsigned char flag=0  ;     //黑线检测测到标志  1--测到
	
char flag_1s=0,flag_stop=0;        //1秒标志
	
unsigned int v,CCD_V;

unsigned char mc[800],speedcnt=0;   //mc用于记录每次转换时，对应的脉冲个数，speedcnt用于记录脉冲个数


int delaytime_value=100;	//延时时间值，单位毫秒
//---------------------------------------------------------------
int K1_flag=0;	//K1按键按下标志

unsigned char key_v=0;		//键值
unsigned char run_display_on=1;

unsigned char DIP_1_FLAG,DIP_2_FLAG,DIP_3_FLAG,DIP_4_FLAG;//拨盘K开关位置标志

uint16_t num =00;		//1毫秒中断计数器
uint16_t AD_num =00;	//1毫秒中断计数器

//-------串行口通讯 变量定义--------
#include "string.h"

const char stringMode1[8]="mode_1#";	//串口调试工具发鿁的字符串命令模弿1
const char stringMode2[8]="mode_2#";	//串口调试工具发鿁的字符串命令模弿2
const char stringStop[8]="stop#";			//串口调试工具发鿁的字符串命令停止模弿
int8_t ledMode=-1;										//串口工作状濁LED显示标志
//模式1-->ledMode=1;模式2-->ledMode=2;停止模式-->ledMode=0;

uint16_t LED_value=0;

uint8_t uart1RxState=0;					//串行通信叿1接收状濁标忿
uint8_t uart1RxCounter=0;				//串行通信叿1接收计数噿
uint8_t uart1RxBuff[128]={0};		//串行通信叿1接收缓冲匿
//-----------------------------------


#define		BATCH_DATA_LEN		4	//DMA数据缓存区长度，必须是鿚道个数的整数忿

uint32_t	dmaDataBuffer[BATCH_DATA_LEN];	//DMA数据缓存区
uint32_t	adc_data[BATCH_DATA_LEN],adc_data_dsp[BATCH_DATA_LEN],AD_DMA[BATCH_DATA_LEN];				//ADC2 in1,in2,in3,in4数据结果

uint32_t	batt_value[8]={0},radd_value[8]={0},photo_res_value[8]={0},moto_value[8]={0};	
//锂电池电压，舵机驱动电源电压，光敏电阻测量值，马达驱动平均电压
uint8_t b=0,r=0,p=0,m=0;//锂电池电压等循环存储AD数组初值
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
/********************************************************/
//         MAIN主函数
/*******************************************************/
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_I2C1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  MX_USART2_UART_Init();
  MX_USART3_UART_Init();
  MX_ADC2_Init();
  MX_TIM5_Init();
  MX_TIM6_Init();
  MX_TIM7_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	

	
	CCD_LIN_Init();//线性CCD初始化
//-------------------------------------------------------------- 
if(HAL_TIM_Base_Start_IT(&htim7)!=HAL_OK)		//使能TIM7的更新中断
			{
				Error_Handler();
			}
//-------------------------------------------------------------- 
		HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);	//启动电机PWM_CHANNEL_1输出
		HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);	//启动电机PWM_CHANNEL_2输出
			
		HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);	//启动舵机PWM_CHANNEL_1输出输出	
		HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);	//启动舵机PWM_CHANNEL_2输出输出	

			
/*		
		rudeer2_control(pwm_value_rudder_middle);	//舵机ch2角度控制（中心位置）		
	
			
		
		rudeer2_control(pwm_value_rudder_middle+200);	//舵机ch2角度控制（左转）		
				HAL_Delay(300);
		
		rudeer2_control(pwm_value_rudder_middle);	//舵机ch2角度控制（中心位置）
			HAL_Delay(300);	
		
		rudeer2_control(pwm_value_rudder_middle-200);	//舵机ch2角度控制（右转）	
			HAL_Delay(300);
		
		rudeer2_control(pwm_value_rudder_middle);	//舵机ch2角度控制（中心位置）
			HAL_Delay(300);				
*/
		moto1_speed_control(pwm_value_motor);//电机ch1速度设置
		moto2_speed_control(pwm_value_motor);//电机ch1速度设置	
		
		HAL_Delay(300);	
		
//-----------------上电开机LCD欢迎画面---------------------------------			
//y轴坐标加8，修改可以新OLED显示偏差问题			
		OLED_init();//OLED初始化
		OLED_Clear(0,8);
		HAL_Delay(30);
		OLED_refresh_gram();
int i=0;	
for(i=0;i<6;i++)
		  OLED_ShowChinese(8+i*18,0,i,16,1,college[i]);
	for(i=0;i<5;i++)
			OLED_ShowChinese(16+i*18,16,i,16,1,college[i+6]);
	for(i=0;i<3;i++)
			OLED_ShowChinese(32+i*18,32,i,16,0,name[i]);
			OLED_ShowString(16,48,"*SMART_CAR*",16);	 //
	HAL_Delay(30);
		OLED_refresh_gram();


		HAL_Delay(3000);
//-----------------上电开机LCD欢迎画面显示3秒---------------------------------		
		
		
			
//------------------------启动ADC2, DMA模式	-------------------------------------- 			
//	HAL_ADC_Start_DMA(&hadc2, dmaDataBuffer, BATCH_DATA_LEN); //启动ADC2, DMA模式	

//			HAL_ADCEx_Calibration_Start(&hadc1);    //ADC1校准(报错？？)
//			HAL_ADCEx_Calibration_Start(&hadc2);    //ADC2校准(报错？？)

//-------------------------------------------------------------- 
//使能usart1中断
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
									printf("hello everyone!.\r\n"); //test
//--------------------------------------------------------------

			

/*
			
//------------------OLED初始匿------------------------------------------			
  OLED_Init();
	OLED_ColorTurn(0);  //
  OLED_DisplayTurn(0); //   
	OLED_Display_On();
int i=0;	
//	OLED_ShowNum(10,10,10,8,8);
//	OLED_ShowChar(0, 0,'C',16);
	
uint8_t A[]="hellow world !!";	
	OLED_Clear();

	OLED_ShowString(0,0,A,16);
	OLED_Refresh();


	OLED_Clear();
	OLED_Refresh();			

*/

//---------------------------------------------------------------------								

		
		


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
 

		
//-------------------拨盘开关位置-------------------
//				测试状态:调节电机速度  DIP=0000
//--------------------------------------------------					
				if (DIP_1==0&DIP_2==0&DIP_3==0&DIP_4==0)   //DIP=0000  测试状态调节电机速度
				{
					OLED_Clear(0,8);
					if (key_v==13) //K2按下 
								{
									pwm_value_motor=pwm_value_motor-2;
									if(pwm_value_motor<=8)
									{
										pwm_value_motor=8;
									}
									
									moto1_speed_control(pwm_value_motor);//电机1速度设置;
									moto2_speed_control(pwm_value_motor);//电机2速度设置;
					//				OLED_Clear(0,2);
					//				OLED_ShowNum(80,0,pwm_value_motor,3,16);
					//				OLED_ShowString(0,0,"pwm_motor:",16);	
													key_v=0;
								
								}	
						if (key_v==12) //K1按下 
								{
									
									pwm_value_motor=pwm_value_motor+2;
									if(pwm_value_motor>=50)
									{
										pwm_value_motor=50;
									}
									moto1_speed_control(pwm_value_motor);//电机1速度设置;
									moto2_speed_control(pwm_value_motor);//电机2速度设置;
						//			OLED_Clear(0,2);
						//			OLED_ShowNum(80,0,pwm_value_motor,3,16);
						//			OLED_ShowString(0,0,"pwm_motor:",16);	
									key_v=0;
								
								}	
					if (key_v==15) //K4按下 _def
								{
								pwm_value_motor_def =pwm_value_motor;	//电机速度初始启动值设罿
						//		OLED_Clear(0,2);	
						//		OLED_ShowNum(88,0,pwm_value_motor,3,16);
						//		OLED_ShowString(0,0,"motor_def:",16);		
								printf("pwm_value_motor_def = %d  ",pwm_value_motor_def);									
								key_v=0;
								}	
								OLED_Clear(0,4);	
								OLED_ShowNum(88,0,pwm_value_motor,3,16);
								OLED_ShowString(0,0,"pwm_motor:",16);
								OLED_ShowNum(88,16,pwm_value_motor_def,3,16);
								OLED_ShowString(0,16,"motor_def:",16);		
				}
//-------------------拨盘开关位置-------------------
//				测试状态:调节舵机ch2角度  DIP=0001
//--------------------------------------------------		
	if (DIP_1==0&DIP_2==0&DIP_3==0&DIP_4==1)   //DIP=0001  测试状态调节舵机ch2角度
				{
			//		OLED_Clear(0,8);
//****************************************************************
//				将线性CCD的输出的模拟信号转为数字信号
//****************************************************************
					CCD_LIN_Init();
					CCD_LIN_Delay(10);//延时20us 
					CCD_LIN_GetImage(aucImageBuf,exposure_time); //获取128个像素数捿
					oled_ccdv();//显示CCD采样数据曲线
					if (key_v==13) //K2按下
					{
						HAL_Delay(20);	//延时20MS
						if (key_v==13) //K2按下确认
								{
									pwm_value_rudder2=pwm_value_rudder2-10;
									
									
									rudeer2_control(pwm_value_rudder2);	//舵机ch2角度控刿	
						
									printf("pwm_value_rudder2 = %d  ",pwm_value_rudder2);
													key_v=0;
								
								}	
					}
						if (key_v==12) //K1按下 
							{
								HAL_Delay(20);	//延时20MS
								if (key_v==12) //K1按下确认
								{
									
									pwm_value_rudder2=pwm_value_rudder2+10;
									
									
									rudeer2_control(pwm_value_rudder2);	//舵机ch2角度控刿
																				
									printf("pwm_value_rudder2 = %d  ",pwm_value_rudder2);
									key_v=0;
								
								}	
							}
						if (key_v==15) //K4按下 
						{
								HAL_Delay(20);	//延时20MS
								if (key_v==15) //K4按下确认
								{
									pwm_value_rudder_middle =pwm_value_rudder2;	//舵机初始中心设置
									OLED_ShowNum(104,0,pwm_value_rudder_middle,4,16);
									OLED_ShowString(0,0,"rudder_middle",16);	
								key_v=0;
								}	
							}
						OLED_Clear(0,4);		
						OLED_ShowNum(88,0,pwm_value_rudder2,4,16);
						OLED_ShowString(0,0,"pwm_rudder:",16);	
						OLED_ShowNum(88,16,pwm_value_rudder_middle,4,16);
						OLED_ShowString(0,16,"rudder_mid:",16);					
		
				}
//-------------------拨盘开关位置-------------------
//				测试状态::usart1通讯测试  DIP=0010
//--------------------------------------------------		
if (DIP_1==0&DIP_2==0&DIP_3==1&DIP_4==0)   //DIP=0010
		{
								if(uart1RxState==1)			//串行通信叿1接收状濿=1,有数据接收到
					{
							if(strstr((const char*)uart1RxBuff,stringMode1)!=NULL)	//接收缓冲区中的字符串是mode_1#,是命令模弿1
							{
								printf("i'm in mode_1!\r\n");	//发鿁i'm in mode_1!给鿚讯的对斿
								ledMode=1;			//串口工作状濁LED显示标志<--1
					HAL_GPIO_TogglePin(GPIOA, redled_pa15_Pin);	
			//					LED_value=0x80;
										
							}
								else if(strstr((const char*)uart1RxBuff,stringMode2)!=NULL) //接收缓冲区中的字符串是mode_2#,是命令模弿2
							{
								printf("i'm in mode_2!\r\n");	//发鿁i'm in mode_2!给鿚讯的对斿
								ledMode=2;			//串口工作状濁LED显示标志<--2
					HAL_GPIO_TogglePin(GPIOA, redled_pa15_Pin);	// Toggle PA15
			//					LED_value=0x01;
										
							}
								else if(strstr((const char*)uart1RxBuff,stringStop)!=NULL)	//接收缓冲区中的字符串是stop#,是命令停止模弿
							{
								printf("i'm in stop!\r\n");	//发鿁i'm in stop!给鿚讯的对斿
								ledMode=0;			//串口工作状濁LED显示标志<--0
					HAL_GPIO_TogglePin(GPIOA, redled_pa15_Pin);	// Toggle PA15
			//					LED_value=0x00;
										
							}
							uart1RxState=0;						//串行通信叿1接收状濁标志清雿
							uart1RxCounter=0;					//串行通信叿1接收计数器清雿
							memset(uart1RxBuff,0,128);//串行通信叿1接收缓冲区清穿
					}
						OLED_Clear(0,8);		
						
						OLED_ShowString(0,0,"uart1_test!",16);
						OLED_ShowString(0,16,"uart1_test!",16);						
		}				
//-------------------拨盘开关位置-------------------
		//				测试状态::电池电压，光线传感器，驱动电机电压  DIP=0011
//--------------------------------------------------									
if (DIP_1==0&DIP_2==0&DIP_3==1&DIP_4==1)   //DIP=0011
		{					
				    printf("AD_DMA_0 = %d  ",AD_DMA[0]);
						printf("AD_DMA_1 = %d  ",AD_DMA[1]);
						printf("AD_DMA_2 = %d  ",AD_DMA[2]);
						printf("AD_DMA_3 = %d  ",AD_DMA[3]);	


//uint32_t	batt_value[8]={0},radd_value[8]={0},photo_res_value[8]={0},moto_value[8]={0};	
//锂电池电压，舵机驱动电源电压，光敏电阻测量值，马达驱动平均电压




	
		
			OLED_Clear(0,8);
			OLED_ShowString(0,0,"battery_v:",16);
				OLED_ShowNum(80,0,adc_data_dsp[0],4,16);
			
			OLED_ShowString(0,16,"rudder_v6:",16);
				OLED_ShowNum(80,16,adc_data_dsp[1],4,16);
			
			OLED_ShowString(0,32,"photo_res:",16);
				OLED_ShowNum(80,32,adc_data_dsp[2],4,16);
			
			OLED_ShowString(0,48,"motor_div:",16);
				OLED_ShowNum(80,48,adc_data_dsp[3],4,16);
					
					
					
					if (key_v==13) //K2按下 
								{
									
													key_v=0;
								
								}	
						if (key_v==12) //K1按下 
								{
									
									
									key_v=0;
								
								}	
			
		
				}					
					
//-------------------拨盘开关位置-------------------
//				测试状态::线性CCD的输出显示测试  DIP=0111
//--------------------------------------------------									
if (DIP_1==0&DIP_2==1&DIP_3==1&DIP_4==1)   //DIP=0111	
{	
//****************************************************************
//				将线性CCD的输出的模拟信号转为数字信号
//****************************************************************
					CCD_LIN_Init();
					CCD_LIN_Delay(10);//延时20us 
					CCD_LIN_GetImage(aucImageBuf,exposure_time); //获取128个像素数捿

		for (i = 0; i < 128; i++)
    {
//			printf("AD%d--%d  ;",i,aucImageBuf[i]); //调试测试串口输出
		}
			OLED_Clear(0,8);
			OLED_ShowString(0,0,"CCD_CAMERA_TEST",16);
			oled_ccdv();//显示CCD采样数据曲线
			OLED_ShowString(0,16,"7654321001234567",16);		
		

//-----------------------按键处理--------------------		
	if (key_v==15) //K4按下  
				{
						key_v=0;
	
				}
				
			if (key_v==14) //K3按下  ccd测试调试
				{
						
						key_v=0;
	
				}
//-----------------------------------------------	  
					
			
			
		
		
		
		
//		HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_15);	

//		HAL_GPIO_TogglePin(GPIOA, redled_pa15_Pin);	
		
if (KEY==0) //F407_KEY
			{
				delaytime_value=200;
			}
else
			{
				delaytime_value=500;
			}
//		HAL_Delay(delaytime_value);
			
	}			
//-------------------拨盘开关位置-------------------
//				智能车工作状态:: DIP=1111
//--------------------------------------------------									
if (DIP_1==1&DIP_2==1&DIP_3==1&DIP_4==1)   //DIP=1111
{
	
//****************************************************************
//				将线性CCD的输出的模拟信号转为数字信号
//****************************************************************
					CCD_LIN_Init();
					CCD_LIN_Delay(10);//延时20us 
	
	
					if(AD_DMA[2]<420&AD_DMA[2]>320)
					{
						exposure_time=200;
					}
					if(AD_DMA[2]<=320)
					{
						exposure_time=150;
					}
					if(AD_DMA[2]>=420&AD_DMA[2]<800)
					{
						exposure_time=150;
					}
					if(AD_DMA[2]>1500)
					{
						exposure_time=255;
					}
	
					CCD_LIN_GetImage(aucImageBuf,exposure_time); //获取128个像素数捿

		for (i = 0; i < 128; i++)
    {
//			printf("AD%d--%d  ;",i,aucImageBuf[i]); //调试测试串口输出
		}
			

		
	//				CCD_DATA_P(); //  处理数据，确定黑线相对位罿 CCD_black
						CCD_DATA_Process();
/************************************************************/
		//	CCD_black	:								30---- 63 ----97	
//  pwm_value_rudder角度设置范围：左----中心----右;
//																		
// pwm_value_rudder = 1660;	//舵机转向角度初始默认1460-1660(中心)-1860
/***********************************************************/	


		if(CCD_black>63-5&CCD_black<63+5)	//   58<ccd_black<68
		{
			pwm_value_rudder=pwm_value_rudder_middle;
			rudeer1_control(pwm_value_rudder);
			pwm_value_motor=45;
			moto1_speed_control(pwm_value_motor_def + 6);//电机1速度设置;
			moto2_speed_control(pwm_value_motor_def + 6);//电机2速度设置;

		}
		
		if(CCD_black>63+5&CCD_black<63+15)	//右小转弯 68-78
		{
			pwm_value_rudder=pwm_value_rudder_middle-(CCD_black-63)*200/55;
			rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
		  pwm_value_motor=38;
      moto1_speed_control(pwm_value_motor_def+5);//电机1速度设置;
			moto2_speed_control(pwm_value_motor_def-3);//电机2速度设置;

		}
		if(CCD_black>=63+15)	//右大转弯 >78
		{
			pwm_value_rudder=pwm_value_rudder_middle-(CCD_black-63)*200/40;
			rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
		  pwm_value_motor=38;
      moto1_speed_control(pwm_value_motor_def+4);//电机1速度设置;4
			moto2_speed_control( pwm_value_motor_def-5);//电机2速度设置;5 

		}
				if(CCD_black>63-15&CCD_black<63-5) 	//左小转弯  48-58
		{
			pwm_value_rudder=pwm_value_rudder_middle+(63-CCD_black)*200/55;
			rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
		  pwm_value_motor=38;
      moto1_speed_control(pwm_value_motor_def-3);//电机1速度设置;
			moto2_speed_control(pwm_value_motor_def+5);//电机2速度设置;

		}
		if(CCD_black<=63-15)	//左大转弯 <48 
		{
			pwm_value_rudder=pwm_value_rudder_middle+(63-CCD_black)*200/40;
			rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
		  pwm_value_motor=38;
      moto1_speed_control(pwm_value_motor_def-5);//电机1速度设置;-5
			moto2_speed_control(pwm_value_motor_def+5);//电机2速度设置;+4

		}
			
/*		               
			if(CCD_black==63)	//回正
			{
			pwm_value_rudder=pwm_value_rudder_middle;
			}
*/      


//       printf("rudder%d--%d ;",CCD_black,pwm_value_rudder); //调试测试串口输出
         
//				rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
                       
/************************************************************/          
//	pwm_value_motor的设置范围：髿------>使
//  													 10 ----->18             
                
//    
//               if( (CCD_black<5)||(CCD_black>85) )     //   <5或>85
		
//							{ 
//							}else 	// 5-85
//							{	
//								pwm_value_motor=40;
//								moto1_speed_control(pwm_value_motor);//电机1速度设置;
//								moto2_speed_control(pwm_value_motor);//电机2速度设置;
//							}

////									moto1_speed_control(pwm_value_motor_def);//电机1速度设置;
////									moto2_speed_control(pwm_value_motor_def+6);//电机2速度设置;




/*---------------------------------------2------------------------------------------------------*/

//		if(CCD_black>63-5&CCD_black<63+5)	//   58<ccd_black<68
//		{
//			pwm_value_rudder=pwm_value_rudder_middle;

//		}
//		
//		if(CCD_black>63+5&CCD_black<63+15)	//右小转弯 68-78
//		{
//			pwm_value_rudder=pwm_value_rudder_middle-(CCD_black-63)*200/55;     
//		  pwm_value_motor=32;
//      moto1_speed_control(pwm_value_motor+5);//电机1速度设置;
//			moto2_speed_control(pwm_value_motor-3);//电机2速度设置;

//		}
//		if(CCD_black>=63+15)	//右大转弯 >78
//		{
//			pwm_value_rudder=pwm_value_rudder_middle-(CCD_black-63)*200/40;    
//		  pwm_value_motor=32;
//      moto1_speed_control(pwm_value_motor+4);//电机1速度设置;4
//			moto2_speed_control( pwm_value_motor-5);//电机2速度设置;5 

//		}

//		
//				if(CCD_black>63-15&CCD_black<63-5) 	//左小转弯  48-58
//		{
//			pwm_value_rudder=pwm_value_rudder_middle+(63-CCD_black)*200/55;     
//		  pwm_value_motor=32;
//      moto1_speed_control(pwm_value_motor-3);//电机1速度设置;
//			moto2_speed_control(pwm_value_motor+5);//电机2速度设置;

//		}
//		if(CCD_black<=63-15)	//左大转弯   <48  53---10
//		{
//			pwm_value_rudder=pwm_value_rudder_middle+(63-CCD_black)*200/35;   
//		  pwm_value_motor=32;
//      moto1_speed_control(pwm_value_motor-5);//电机1速度设置;-5
//			moto2_speed_control(pwm_value_motor+6);//电机2速度设置;+4

//		}
//			
///*		               
//			if(CCD_black==63)	//回正
//			{
//			pwm_value_rudder=pwm_value_rudder_middle;
//			}
//*/      


////       printf("rudder%d--%d ;",CCD_black,pwm_value_rudder); //调试测试串口输出
//         
//				rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
//                       
///************************************************************/          
////	pwm_value_motor的设置范围：髿------>使
////  													 10 ----->18             
////                
////    
//               if( (CCD_black<5)||(CCD_black>85) )     //   <5或>85
//		
//							{ 
//							}else 	// 5-85
//							{	
//								pwm_value_motor=40;
//								moto1_speed_control(pwm_value_motor);//电机1速度设置;
//								moto2_speed_control(pwm_value_motor);//电机2速度设置;
//							}



/*----------------------------------------1-----------------------------------------------------*/

////初始方案

//		if(CCD_black>63-5&CCD_black<63+5)	//
//		{
//			pwm_value_rudder=pwm_value_rudder_middle;

//		}
//		
//		if(CCD_black>63+5&CCD_black<63+15)	//右小转弯                                                                                                      
//		{
//			pwm_value_rudder=pwm_value_rudder_middle-(CCD_black-63)*200/55;
//			

//		}
//		if(CCD_black>=63+15)	//右大转弯
//		{
//			pwm_value_rudder=pwm_value_rudder_middle-(CCD_black-63)*200/40;
//			

//		}
//		if(CCD_black>63-15&CCD_black<63-5)	//左小转弯
//		{
//			pwm_value_rudder=pwm_value_rudder_middle+(63-CCD_black)*200/55;

//		}
//		if(CCD_black<=63-15)	//左大转弯
//		{
//			pwm_value_rudder=pwm_value_rudder_middle+(63-CCD_black)*200/40;

//		}
//			
///*		               
//			if(CCD_black==63)	//回正
//			{
//			pwm_value_rudder=pwm_value_rudder_middle;
//			}
//*/      
////       printf("rudder%d--%d ;",CCD_black,pwm_value_rudder); //调试测试串口输出
//         
//							rudeer1_control(pwm_value_rudder);	//舵机转向角度控制输出      
//         
// 				
//			
//	
//                
///************************************************************/          
////	pwm_value_motor的设置范围：髿------>使
////  													 10 ----->18             
//                
//    
////               if( (CCD_black<5)||(CCD_black>85) )             //如果高鿟过弯，漂移速度降到驱动很弱尿
////								{   
////									pwm_value_motor=30;                                  ;
////                 	moto1_speed_control(pwm_value_motor);//电机1速度设置;
////									moto2_speed_control(pwm_value_motor);//电机2速度设置;
////									
////								}
////                else 	//根据黑线相对位置，舵机转向角度，计算调整智能车鿟度
////									{						
////									pwm_value_motor=38;
////									moto1_speed_control(pwm_value_motor);//电机1速度设置;
////									moto2_speed_control(pwm_value_motor);//电机2速度设置;
////									}

//									moto1_speed_control(pwm_value_motor_def);//电机1速度设置;
//									moto2_speed_control(pwm_value_motor_def+6);//电机2速度设置;








//-----------------------按键处理--------------------		
if (key_v==15) //K4按下 OLED  显示参数 
				{
						key_v=0;
					run_display_on=1;
	
				}
				
				if (key_v==14) //K3按下  OLED  不显示参数
				{
						
						key_v=0;
					run_display_on=0;
				}
if (run_display_on==1) //K4按下
{				
		OLED_Clear(0,8);
		OLED_ShowString(0,0,"CCD_black:",16);
		OLED_ShowNum(80,0,CCD_black,4,16);
		OLED_ShowString(0,16,"pwm_rudder:",16);
		OLED_ShowNum(80,16,pwm_value_rudder,4,16);
		oled_ccdv();//显示CCD采样数据曲线
}	
					
//-----------------------------------------------	  



}
//-------------------拨盘开关位置-------------------
//				智能车工作状态:: DIP=1111
//----------------------end--------------------------				
//-------------------------------------------------------------											
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		OLED_refresh_gram();
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

//*****************************************************************************/
//	功能描述  : TIME7皿1ms定时中断Callback
//	输入参数  : 84000000	//time work_clk  
//	输出参数  : 100ms led灯（PA15）翻转一轿
//						:	1000ms 启用DMA的ADC2转换 结果存入AD_DMA[4]
//	备注			: 
//*****************************************************************************/
void	HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim)
{
	if(TIM7 == htim->Instance)
	{
		num++;AD_num++;
		if(num==100)	//100ms
		{
			num=00;
			HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_15);		//100ms翻转led灿
		}
		
		if(AD_num==200)	//1000ms
		{
			AD_num=00;
			
			HAL_ADC_Start_DMA(&hadc2, AD_DMA, 4); 
		//启用DMA的ADC转换，AD_DMA[] 0~3 对应ADC2 1--4CH，这里注意最后一个参数的大小
		}
	



		
	}
}

//-------------------------------------------------------
//USART1,2,3中断请求服务
//-------------------------------------------------------
void USER_UART_IRQHandler(void)    //用户自定义的USART中断接收服务程序
{
	if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET)
			{
					__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
				uart1RxBuff[uart1RxCounter]=(uint8_t)(huart1.Instance->DR&(uint8_t)0x00ff);
				uart1RxCounter++;
				__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
			}

	if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)
			{	
					__HAL_UART_DISABLE_IT(&huart1,UART_IT_IDLE);
					uart1RxState=1;

			}

}
//*****************************************************************************/
//	功能描述  : ADC-DMA传输完成事件中断的回调函数
//	输入参数  : ADC2 IN1,IN2,IN3,IN4 四个通道的模拟量输入
//	输出参数  : 四个通道的模数转换结果AD_DMA[],adc_data[]
//	 备注			:
//*****************************************************************************/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	HAL_ADC_Stop_DMA(&hadc2); //停止DMA的ADC2转换，AD_DMA 0~3 对应ADC 0~3
    HAL_TIM_Base_Stop_IT(&htim7);//关闭定时器
	int i=0;	
		for (i=0;i<4;i++)
		{
		adc_data[i]=AD_DMA[i];
		}

//    printf("AD_DMA_0 = %d  ",AD_DMA[0]);
//    printf("AD_DMA_1 = %d  ",AD_DMA[1]);
//    printf("AD_DMA_2 = %d  ",AD_DMA[2]);
//		printf("AD_DMA_3 = %d  ",AD_DMA[3]);
//   HAL_TIM_Base_Start_IT(&htim7); //开启定时器
 
		
//batt_value[8]	循环存储AD采样值		
				batt_value[b]=adc_data[0];
				b++;
				if(b>7)
				{
					b=0;
				}
//----------------------
//计算AD平均值
			adc_data_dsp[0]=0;
			for (i=0;i<8;i++)
		{
		adc_data_dsp[0]=adc_data_dsp[0]+batt_value[i];
		}
	adc_data_dsp[0]=adc_data_dsp[0]/8;
//----------------------		
//uint32_t	batt_value[8]={0},radd_value[8]={0},photo_res_value[8]={0},moto_value[8]={0};	
//锂电池电压，舵机驱动电源电压，光敏电阻测量值，马达驱动平均电压
//uint8_t b=0,r=0,p=0,m=0;//锂电池电压等循环存储AD数组初值

//radd_value[8]	循环存储AD采样值		
				radd_value[r]=adc_data[1];
				r++;
				if(r>7)
				{
					r=0;
				}
//----------------------
//计算AD平均值
			adc_data_dsp[1]=0;
			for (i=0;i<8;i++)
		{
		adc_data_dsp[1]=adc_data_dsp[1]+radd_value[i];
		}
	adc_data_dsp[1]=adc_data_dsp[1]/8;
//----------------------				
		adc_data_dsp[0]=(3300*adc_data_dsp[0]/4095*15.8/5);
		adc_data_dsp[1]=(3300*adc_data_dsp[1]/4095*2);
		adc_data_dsp[2]=adc_data[2];
		adc_data_dsp[3]=(3300*adc_data[3]/4095*26/5);
		
   HAL_TIM_Base_Start_IT(&htim7); //开启定时器		
		for (i=0;i<4;i++)
		{
		printf("%d--%d;\n",i,adc_data_dsp[i]); //调试测试串口输出
		}
		
	}



//-------------------------------------------------------
//独立按键键盘外部中断回调函数
//-------------------------------------------------------
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	
	
	int back_pin;
	back_pin=GPIO_Pin;
	
	if(back_pin&GPIO_PIN_12)
	{		
		key_v=12;	//k1
		
	}
	if(back_pin&GPIO_PIN_13)
	{
		key_v=13;	//k2
		
	}
	if(back_pin&GPIO_PIN_14)
	{
		key_v=14;		//k3
		
	}
if(back_pin&GPIO_PIN_15)
	{
		key_v=15;		//k4
		
	}
	
}

/*****************************************************************************
 延时函数  : CCD_LIN_Delay
 功能描述  : 线性CCD延时函数
 输入参数  : NONE  
 输出参数  : NONE
 备注      : 
*****************************************************************************/
void CCD_LIN_Delay(unsigned int CCD_DELAY_TIME)
{
    unsigned int i,j;
        for (i = CCD_DELAY_TIME; i > 0; i--)
					{
						 for(j = 15; j > 0; j--);
					}
    return;
}

/*****************************************************************************
 : CCD_LIN_Init
 功能描述  : 线性CCD模块初始化
 输入参数  : NONE  
 输出参数  : NONE
 备注			 : 
SET_CCD_LIN_SI 				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);	//CCD_LIN_SI = 1;
RESET_CCD_LIN_SI 			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);	//CCD_LIN_SI = 0;
SET_CCD_LIN_CK 				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);//CCD_LIN_CK = 1;
RESET_CCD_LIN_CK 			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);//CCD_LIN_CK = 0;   

*****************************************************************************/
void CCD_LIN_Init(void)
{
   RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0; 
   RESET_CCD_LIN_SI;	//CCD_LIN_SI = 0; 
	return;
}
/*****************************************************************************
  : CCD_LIN_GetImage
 功能描述  : 获得线性CCD输出的图像信息
	CLK-----PC0 时钟输入，控制电荷转移，像素点输出和复位
  SI------PC1 序列输入，标志数据序列的数值
 输入参数  : UCHAR8 *pucImageBuf  存放128个AD转换结果的缓存地址指针，
							exposure_time：曝光时间
 输出参数  : pucImageBuf  128个AD转换结果 8位）
 : NONE
*****************************************************************************/
void CCD_LIN_GetImage(unsigned char *pucImageBuf,unsigned char exposure_time)
{
	unsigned int i,time_us=1;
    RESET_CCD_LIN_SI;	//CCD_LIN_SI = 0;
    SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1;
//		CCD_LIN_Delay(time_us);//延时 
		
		SET_CCD_LIN_SI ;	//CCD_LIN_SI = 1;
		RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
		//CCD_LIN_Delay(time_us);//延时 
	
		SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1;
		RESET_CCD_LIN_SI;	//CCD_LIN_SI = 0;
//		CCD_LIN_Delay(time_us);//延时 
	
		for (i = 0; i < 128; i++)
    {
       RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
			  
				CCD_LIN_Delay(time_us*exposure_time);  //调节曝光时间 
				HAL_ADC_Start(&hadc1);
				HAL_ADC_PollForConversion(&hadc1,0);
				adc_value = HAL_ADC_GetValue(&hadc1);	//将线性CCD的输出的模拟信号转为数字信号
        adc_8bit = adc_value>>4;		//取A/D数据的高8位
				pucImageBuf[i] = adc_8bit;
			
				SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
//       CCD_LIN_Delay(time_us); 
    }
    RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0 
//    CCD_LIN_Delay(time_us);

    return;
}
/*****************************************************************************
 : CCD_LIN_GetImage_new
 功能描述  : 获得线濧CCD输出的图像信叿
	CLK  PC0 时钟输入，控制电荷转移，像素点输出和复位
  SI  PC1  序列输入，标志数据序列的弿姿
 输入参数  : UCHAR8 *pucImageBuf  存放128个AD转换结果的缓存地坿
 输出参数  : pucImageBuf  128个AD转换结果＿8位）
 : NONE
*****************************************************************************/
void CCD_LIN_GetImage_new(unsigned char *pucImageBuf)
{
    unsigned int i;
    RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
		CCD_LIN_Delay(20);//延时 
		SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
	  CCD_LIN_Delay(20);//延时 
	
		RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
		CCD_LIN_Delay(20);//延时 
		SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
	  CCD_LIN_Delay(20);//延时 
		RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
	
		SET_CCD_LIN_SI ;	//CCD_LIN_SI = 1;
		CCD_LIN_Delay(20);//延时
		SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
		CCD_LIN_Delay(20);//延时	
		RESET_CCD_LIN_SI;	//CCD_LIN_SI = 0;
//		CCD_LIN_Delay(20);//延时
		
	
	
		for(i=0;i<129;i++)
		{
			CCD_LIN_Delay(20);//延时
			RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
			CCD_LIN_Delay(20);//延时
			SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
		}
		
		//从这里结束曝兿
		CCD_LIN_Delay(200);  //延时时间长，CCD中的电容器能获得足够的积累电荷时间，达到饱和稳定状濿
                        //但是时间过长采集频率会下降，承以根据实际图像效果调整延旿
	

		
		SET_CCD_LIN_SI ;	//CCD_LIN_SI = 1;
		CCD_LIN_Delay(20);//延时
    SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
		
		CCD_LIN_Delay(20);//延时 
		RESET_CCD_LIN_SI;	//CCD_LIN_SI = 0;
	
		for (i = 0; i < 128; i++)
    {
      CCD_LIN_Delay(20);  //延时
			RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0
        HAL_ADC_Start(&hadc1);
				HAL_ADC_PollForConversion(&hadc1,2);
				adc_value = HAL_ADC_GetValue(&hadc1);	//将线性CCD的输出的模拟信号转为数字信号
        adc_8bit = adc_value>>4;		//取A/D数据的高8使
				pucImageBuf[i] = adc_8bit;
			CCD_LIN_Delay(20);  //延时
			SET_CCD_LIN_CK ;	//CCD_LIN_CK = 1
			
    }
    
    RESET_CCD_LIN_CK;	//CCD_LIN_CK = 0 
    CCD_LIN_Delay(44);

    return;
}

/*
void RD_TSL(void) 
{
	u8 i=0,tslp=0;
		
	static u8 j,Left,Right,Last_CCD_Zhongzhi;
	static u16 value1_max,value1_min;
		
	TSL_CLK=1;     //CLK引脚设为高电广          
	TSL_SI=0; 
	Dly_us(TIME_us);
				
	TSL_SI=1; 
	TSL_CLK=0;
	Dly_us(TIME_us);
				
	TSL_CLK=1;
	TSL_SI=0;
	Dly_us(TIME_us); 
	for(i=0;i<128;i++)
	{ 
		TSL_CLK=0; 
		Dly_us(TIME_us);  //调节曝光时间
		ccd_adc[tslp]=(u8)((float)Get_Adc(ADC_Channel_1)/4096*255);  //将读取到的电压忼存入数组中
		++tslp;
		TSL_CLK=1;
		Dly_us(TIME_us);
	} 

	value1_max=ccd_adc[0];  //动濁阈值算法，读取朿大和朿小忿
	for(i=5;i<123;i++)   //两边各去掿5个点
	{
		if(value1_max<=ccd_adc[i])
		value1_max=ccd_adc[i];
	}
	value1_min=ccd_adc[0];  //朿小忿
	for(i=5;i<123;i++) 
	{
		if(value1_min>=ccd_adc[i])
		{
			value1_min=ccd_adc[i];				
		}
	 }
	 CCD_Yuzhi=(value1_max+value1_min)/2;	  //计算出本次中线提取的阈忿
	 for(i = 5;i<118; i++)   //寻找左边跳变沿
	 {
		if(ccd_adc[i]>CCD_Yuzhi&amp;&amp;ccd_adc[i+1]>CCD_Yuzhi&amp;&amp;ccd_adc[i+2]>CCD_Yuzhi&amp;&amp;ccd_adc[i+3]<CCD_Yuzhi&amp;&amp;ccd_adc[i+4]<CCD_Yuzhi&amp;&amp;ccd_adc[i+5]<CCD_Yuzhi)
		{	
			Left=i;
			break;	
		}
	 }
	 for(j = 118;j>5; j--)//寻找右边跳变沿
	 {
		if(ccd_adc[j]<CCD_Yuzhi&amp;&amp;ccd_adc[j+1]<CCD_Yuzhi&amp;&amp;ccd_adc[j+2]<CCD_Yuzhi&amp;&amp;ccd_adc[j+3]>CCD_Yuzhi&amp;&amp;ccd_adc[j+4]>CCD_Yuzhi&amp;&amp;ccd_adc[j+5]>CCD_Yuzhi)
		{	
			Right=j;
			break;	
		}
	 }
	CCD_Zhongzhi=(Right+Left)/2;//计算中线位置
	if(myabs(CCD_Zhongzhi-Last_CCD_Zhongzhi)>70)   //计算中线的偏差，如果太大
	CCD_Zhongzhi=Last_CCD_Zhongzhi;    //则取上一次的倿
	Last_CCD_Zhongzhi=CCD_Zhongzhi;  //保存上一次的偏差	
		
}

*/

/*****************************************************************************
 凿 敿 吿  : CCD_DATA_Process
 功能描述  : 线濧CCD数据预处琿
 输入参数  : aucImageBuf[127]  
 输出参数  : 黑线位置:CCD_black; flag黑线测到标志 1
 迿 囿 倿  : 
*****************************************************************************/
void CCD_DATA_Process(void)
{
	 unsigned int i;
//	 unsigned int j,Left=0,Right=0;
//	 unsigned int Last_CCD_Zhongzhi,CCD_Yuzhi;
   unsigned int CCD_V_MIN=255;
	   for (i = 0; i < 127; i++)
				{
						CCDBuf[i]=aucImageBuf[i];    //
				}
	
			if(CCD_black>63+5)
				{
					for(i=127-29;i<=127;i++)
						{
						CCDBuf[i]=255;
						}
				}
			 if(CCD_black<63-5)
				{
					for(i=0;i<=29;i++)
						{
						CCDBuf[i]=255;
						}
				}
			
		for(i=16;i<111;i++)   // i=8;i<119 两边各去8个点
			{
//		printf("CCDBuf[%d]--%d ;"i,CCDBuf[i]); //调试测试串口输出
				if(CCD_V_MIN>=CCDBuf[i])
				{
					CCD_V_MIN=CCDBuf[i];//找黑线位置（最小值）
					
					CCD_black=i;
				}
			}
				
			
			if(abs(Last_CCD_black-CCD_black)>30)   //计算与上次偏差，如果太大
					{
						CCD_black=Last_CCD_black;    //则取上一次的
					}
			Last_CCD_black=CCD_black;  //保存上一次的偏差	

//		printf("CCD_black--%d ;",CCD_black); //调试测试串口输出
}


/*****************************************************************************/
 

 /*****************************************************************************
 凿 敿 吿  : CCD_DATA_P
 功能描述  : 线濧CCD数据预处琿
 输入参数  : aucImageBuf  
 输出参数  : 黑线位置:CCD_black ; flag黑线棿测到标志 1
 迿 囿 倿  : 
*****************************************************************************/
void CCD_DATA_P(void)
{
    unsigned int i;
    unsigned int CCD_V_MIN=255;
 //     CCD_black=0;
    for (i = 0; i < 127; i++)
			{
					CCDBuf[i]=aucImageBuf[i];    //CCD采样数据存入CCDBuf
			}
//		if(CCD_black<63+20&&CCD_black>62-20)
			{
				for(i=0;i<=29;i++)
					{
					CCDBuf[i]=255;
					}
				for(i=127-29;i<=127;i++)
					{
					CCDBuf[i]=255;
					}
			}
			
/*		if(CCD_black>=63+20)
		{
			for(i=0;i<=39;i++)
			{
				CCDBuf[i]=255;
			}
		
		}
		
		if(CCD_black<=63-20)
		{
			for(i=127-39;i<=127;i++)
			{
				CCDBuf[i]=255;
			}
		}	
*/		
      for (i = 0; i < 127; i++)
      {
        if( CCDBuf[i] <  CCD_V_MIN)     // 确定黑线位置朿小忿 20160422wf
         {
          CCD_V_MIN = CCDBuf[i];
          CCD_black=i;             //
         }
       
        
     }
    
		
	

    
    return;  
}
/*****************************************************************************
 凿 敿 吿  : SYSTEM_TIME_Delay
 功能描述  : 延时函数 
 输入参数  : USHORT16 usTime
 输出参数  : NONE
 迿 囿 倿  : NONE
*****************************************************************************/
void SYSTEM_TIME_Delay(unsigned int usTime)
{
    unsigned int i,j;          //32WORD
    for (i =  100 * usTime; i > 0; i--)
    {
        for(j = 210; j > 0; j--)
        {
        }
    }
    return;
}
/********************************************************/
//功能：设置电机占空比,改变电机速度
//PA6     ------> TIM3_CH1	motor drive
//  htim3.Init.Prescaler = 84-1;
//  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
//  htim3.Init.Period = 125-1;
//  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
//  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
//	电机PWM驱动频率设置8khz
//	pwm_value_motor的设置范围：髿------>使
//  													 ??? ----->???
/********************************************************/   
void  moto1_speed_control(unsigned char pwm_value_motor)
{
			
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,pwm_value_motor);  //设置电机1占空毿
      
	return;
}
void  moto2_speed_control(unsigned char pwm_value_motor)
{
			
			__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,pwm_value_motor);  //设置电机2占空毿
      
	return;
}
/***********************************************************/   

/************************************************************/
//入口：舵机占空比参数设置
//出口：无
//功能：设置舵机占空比，改变舵机转动角庿
//	 	TIM2 GPIO Configuration
//    PA5     ------> TIM2_CH1
//    PB3     ------> TIM2_CH2
//		htim2.Instance = TIM2;
//	  htim2.Init.Prescaler = 84-1;
//	  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
//	  htim2.Init.Period = 2000-1;
//	  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
//	  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
/************************************************************/
//  pwm_value_rudder角度设置范围＿ 叿----中心-------巿;
//					Middle_Value+-200
//  													    1470---1670(中心)-1810
/***********************************************************/
void  rudeer1_control(unsigned int pwm_value_rudder)
{
             
     __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,pwm_value_rudder); //设置舵机占空比
			
         return;
}
void  rudeer2_control(unsigned int pwm_value_rudder)
{
             
     __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,pwm_value_rudder); //设置舵机占空比（测试)
			
         return;
}
//****************************************************************			
	 
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
